package org.travelfusion.xmlclient.ri.handler.misc;

import java.util.HashMap;
import java.util.Map;

import javax.xml.stream.XMLStreamConstants;

import org.travelfusion.xmlclient.handler.HandlesRequestsFor;
import org.travelfusion.xmlclient.impl.handler.AbstractXmlToolRequestStAXResponseHandler;
import org.travelfusion.xmlclient.ri.xobject.misc.XAirportInfo;
import org.travelfusion.xmlclient.ri.xobject.misc.XAirportName;
import org.travelfusion.xmlclient.ri.xobject.misc.XCity;
import org.travelfusion.xmlclient.ri.xobject.misc.XCountry;
import org.travelfusion.xmlclient.ri.xobject.misc.XGetAirportsDataRequest;
import org.travelfusion.xmlclient.ri.xobject.misc.XGetAirportsDataResponse;

@HandlesRequestsFor(XGetAirportsDataRequest.class)
public class GetAirportsDataHandler extends AbstractXmlToolRequestStAXResponseHandler<XGetAirportsDataRequest, XGetAirportsDataResponse> {

	@Override
	protected void fillTemplate() throws Exception {
	}

	@Override
	public XGetAirportsDataResponse handleResponse() throws Exception {
		
		Map<String, XAirportInfo> airportsMap = new HashMap<String, XAirportInfo>();
		Map<String, XAirportName> airportNameMap = new HashMap<String, XAirportName>();

		StringBuilder builder = new StringBuilder(32);

		XAirportInfo airportInfo = null;
		XAirportName airportName = null;
		XCountry country = null;
		XCity city = null;
		String currentName = null;

		done : for (int event; ((event = responseReader.next()) != XMLStreamConstants.END_DOCUMENT);) {
			switch (event) {
				case XMLStreamConstants.START_ELEMENT :
					builder.setLength(0);
					currentName = responseReader.getName().getLocalPart();
					if (airportInfo == null) {
						if ("Airport".equals(currentName)) {
							airportInfo = new XAirportInfo();
							airportNameMap = new HashMap<String, XAirportName>();
						}
					} else {
						if (airportName == null) {
							if ("AirportName".equals(currentName)) {
								airportName = new XAirportName();
							}
						} 
						if (country == null) {
							if ("Country".equals(currentName)) {
								country = new XCountry();
							}
						}
						if (city == null) {
							if ("City".equals(currentName)) {
								city = new XCity();
							}
						}
					}
					break;
				case XMLStreamConstants.CHARACTERS :
					if (airportInfo != null) {
						builder.append(responseReader.getTextCharacters(), responseReader.getTextStart(), responseReader.getTextLength());
					}
					break;
				case XMLStreamConstants.END_ELEMENT :
					if (airportInfo != null) {
						currentName = responseReader.getName().getLocalPart();
						if (country != null) {
							if ("CountryName".equals(currentName)) {
								country.setName(builder.toString().trim());
							} else if ("CountryCode".equals(currentName)) {
								country.setCode(builder.toString().trim());
							} else if ("Country".equals(currentName)) {
								airportInfo.setCountry(country);
								country = null;
							}
						}
						
						if (city != null) {
							if ("CityName".equals(currentName)) {
								city.setName(builder.toString().trim());
							} else if ("CityCode".equals(currentName)) {
								city.setCode(builder.toString().trim());
							} else if ("City".equals(currentName)) {
								airportInfo.setCity(city);
								city = null;
							}
						}
						
						if (airportName != null) {
							if ("Language".equals(currentName)) {
								airportName.setLanguage(builder.toString().trim());
							} else if ("LanguageCode".equals(currentName)) {
								airportName.setLanguageCode(builder.toString().trim());
							} else if ("Name".equals(currentName)) {
								airportName.setName(builder.toString().trim());
							} else if ("AirportName".equals(currentName)) {
								airportNameMap.put(airportName.getLanguageCode(), airportName);
								airportName = null;
							}
						}

						if ("IataCode".equals(currentName)) {
							airportInfo.setIataCode(builder.toString().trim());
						} else if ("Airport".equals(currentName)) {
							airportInfo.setAirportNamesMap(airportNameMap);
							airportsMap.put(airportInfo.getIataCode(), airportInfo);
							airportInfo = null;
						}
					} else if ("AirportList".equals(currentName)) {
						break done;
					}
					currentName = null;
					break;
			}
		}

		XGetAirportsDataResponse response = new XGetAirportsDataResponse();
		response.setAirportsMap(airportsMap);
		return response;
	}

}
